home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 3: CDPD 3
/
Almathera Ten on Ten - Disc 3: CDPD3.iso
/
fish
/
676-700
/
676
/
fbm
/
fbm10ami.zoo
/
gif2fbm.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-06-11
|
11KB
|
494 lines
/* GIF2FBM.c -- Convert GIF to FBM acting as a filter */
/* GIF-decompession-routine partially taken from xgif.c */
/* Works also for interlaced GIF-Files */
/* Compilation: SAS/C 5.10: "LC -Lcdm -O -cr -v -w gif2hl.c" */
/* SYS V Unix compiler: "cc -o gif2fbm -DSYSV -O gif2fbm.c" */
#include <stdio.h>
#define MAX(a,b) ((a)>(b)?(a):(b))
#define MIN(a,b) ((a)<(b)?(a):(b))
#define ABS(x) ((x<0)?(-(x)):(x))
#ifdef SYSV
#include <malloc.h>
#endif
#ifdef AZTEC_C
#include <functions.h>
#include <stdlib.h>
#endif
#ifdef LATTICE
#include <stdlib.h>
#include <string.h>
#define ANSI_C
#endif
typedef unsigned char UBYTE;
typedef unsigned short UWORD;
typedef unsigned long ULONG;
#define ILL_PAR 102
#define NO_MEM 100
#define NOT_INP 104
#define NOT_OUT 105
/* #define DEBUG */
#ifdef ANSI_C
UWORD fget16(FILE *);
void AddToPixel(UBYTE);
void WriteFBM(UWORD, UWORD);
UBYTE getubyte();
UWORD getbits(short);
#endif
/* Globale Variablen */
static UBYTE *PixelBuffer[2048];
static char *Cregs;
static UWORD Prefix[4096], Suffix[4096];
static UWORD OutCode[1025];
char Interlace;
unsigned long TCounter = 0;
char FileTerminate = 0;
static UWORD XC = 0,
YC = 0,
Pass = 0,
OutCount = 0,
RWidth, RHeight,
Width, Height,
LeftOfs, TopOfs,
CodeSize;
static UBYTE background;
static float aspect = 1.0;
# define FBM_MAX_TITLE 80 /* For title and credits */
# define BLACK 0 /* For 8bit files */
# define WHITE 255 /* For 8bit files */
# define BYTE 256 /* For 8bit files */
# define BLANKS " "
# define FBM_MAGIC "%bitmap"
/* FBM bitmap headers in files (null terminated 12 character ascii strings) */
typedef struct fbm_filehdr_struct {
char magic[8]; /* 8 bytes FBM_MAGIC number */
char cols[8]; /* Width in pixels */
char rows[8]; /* Height in pixels */
char planes[8]; /* Depth (1 for B+W, 3 for RGB) */
char bits[8]; /* Bits per pixel */
char physbits[8]; /* Bits to store each pixel */
char rowlen[12]; /* Length of a row in bytes */
char plnlen[12]; /* Length of a plane in bytes */
char clrlen[12]; /* Length of colormap in bytes */
char aspect[12]; /* ratio of Y to X of one pixel */
char title[FBM_MAX_TITLE]; /* Null terminated title */
char credits[FBM_MAX_TITLE]; /* Null terminated credits */
} FBMFILEHDR;
static UWORD fget16(fp)
register FILE *fp;
{
register UBYTE b1,b2;
b1=getc(fp);
b2=getc(fp);
return((UWORD)b1 | ((UWORD)b2 << 8));
}
/* getubyte: get a byte from blocked file */
/* returns byte in <ch> and a return value of 0 in <FileTerminate> if ok */
/* uses global variables <count>, <FileTerminate> and <stdin> */
short count = 0;
UBYTE getubyte()
{
register UBYTE ch;
if (feof(stdin)) {
FileTerminate=!0;
return(0);
};
if (count != 0) {
ch = getc(stdin);
count--;
}
else {
count = getc(stdin);
if (count==0) {
FileTerminate=!0;
return(0);
};
ch = getc(stdin);
count--;
};
return(ch);
}
short bitcount = 0;
UWORD restbits = 0;
UWORD getbits(bits)
register short bits;
{
register UWORD w;
register UBYTE mask;
register short shift;
register UBYTE c;
w = 0;
shift = 0;
while (bits != 0) {
if (bitcount==0) {
c=getubyte();
if (FileTerminate) {
return(w);
};
if (bits>=8) {
w |= ((UWORD)c << shift);
bits -= 8;
shift += 8;
restbits = 0;
}
else {
mask = 0xff;
mask >>= (8-bits);
w |= ((c & mask) << shift);
restbits = c >> bits;
bitcount = 8-bits;
shift += bits;
bits = 0;
};
}
else { /* bitcount > 0 */
if (bits>=bitcount) {
w |= (restbits << shift);
bits -= bitcount;
shift += bitcount;
bitcount=0;
restbits = 0;
}
else { /* bits < bitcount */
mask = 0xff;
mask >>= (8-bits);
w |= ((restbits & mask) << shift);
restbits >>= bits;
bitcount -= bits;
shift += bits;
bits = 0;
};
};
}; /* while */
#ifdef DEBUG
printf(" |%u| ",(unsigned)w);
#endif
return(w);
}
void AddToPixel(Index)
UBYTE Index;
{
register UBYTE *ptr;
#ifdef DEBUG
printf(" {%x} ",(unsigned)Index);
#endif
if (YC < Height) {
ptr = PixelBuffer[YC];
ptr += (unsigned long)XC;
*ptr = Index;
if (++XC == Width) {
XC=0;
if (!Interlace) YC++;
else {
switch(Pass) {
case 0:
YC += 8;
if (YC >= Height) {
Pass++;
YC=4;
};
break;
case 1:
YC += 8;
if (YC >= Height) {
Pass++;
YC=2;
};
break;
case 2:
YC += 4;
if (YC >= Height) {
Pass++;
YC=1;
};
break;
case 3:
YC += 2;
break;
default:
break;
};
};
};
};
}
/* Write a 24-bit file for FBM */
void WriteFBM(height,width)
UWORD height,width;
{
register UWORD i,j;
register UBYTE *ptr;
UBYTE *colptr;
UWORD rowlen;
FBMFILEHDR *fbm_hdr;
rowlen = 2 * ((width * 8 + 15) / 16);
if ((fbm_hdr=malloc(sizeof(FBMFILEHDR))) == NULL) {
fprintf(stderr,"Not enough memory for malloc()\n");
exit(NO_MEM);
};
strncpy(fbm_hdr->magic,FBM_MAGIC,8);
sprintf(fbm_hdr->cols,"%7u",(unsigned)width);
sprintf(fbm_hdr->rows,"%7u",(unsigned)height);
sprintf(fbm_hdr->planes,"%7u",3);
sprintf(fbm_hdr->bits,"%7u",8);
sprintf(fbm_hdr->physbits,"%7u",8);
sprintf(fbm_hdr->rowlen,"%11u",(unsigned)rowlen);
sprintf(fbm_hdr->plnlen,"%11lu",(ULONG)rowlen*(ULONG)height);
sprintf(fbm_hdr->clrlen,"%11u",0);
sprintf(fbm_hdr->aspect,"%11.6f",aspect);
strncpy(fbm_hdr->title,"",80);
strncpy(fbm_hdr->credits,"",80);
fwrite(fbm_hdr,1,sizeof(FBMFILEHDR),stdout);
free(fbm_hdr);
/* Write RED plane */
for (i=0; i<height; i++) {
ptr = PixelBuffer[i];
for (j=0; j<width; j++) {
colptr=Cregs + (ULONG)(*(ptr+(ULONG)j) * 3);
putchar(*colptr);
};
for (j=width; j<rowlen; j++) putchar('\0');
};
/* Write GREEN plane */
for (i=0; i<height; i++) {
ptr = PixelBuffer[i];
for (j=0; j<width; j++) {
colptr=Cregs + (ULONG)(*(ptr+(ULONG)j) * 3 + 1);
putchar(*colptr);
};
for (j=width; j<rowlen; j++) putchar('\0');
};
/* Write BLUE plane */
for (i=0; i<height; i++) {
ptr = PixelBuffer[i];
for (j=0; j<width; j++) {
colptr=Cregs + (ULONG)(*(ptr+(ULONG)j) * 3 + 2);
putchar(*colptr);
};
for (j=width; j<rowlen; j++) putchar('\0');
};
}
main()
{
UWORD Colors;
UWORD sWidth, sHeight;
UBYTE gFlags;
UWORD iWidth, iHeight, iLeft, iTop;
UWORD iCol,
Code,
MaxCode,
ClearCode,
EOFCode,
OldCode,
InCode,
FirstFree,
FinChar,
BitMask,
InitCodeSize,
BitsPerPixel;
UBYTE iFlags;
UBYTE c;
UBYTE AspByte; /* Aspect Ratio information */
int n;
char IDbuffer[6];
register UWORD FreeCode, CurCode;
register short i;
n=fread(IDbuffer,6,1,stdin);
if (strncmp(IDbuffer,"GIF87a",6)!=0) {
fprintf(stderr,"GIF87a - ID not found\n");
exit(30);
};
sWidth = Width = fget16(stdin);
sHeight = Height = fget16(stdin);
gFlags = (UBYTE)getc(stdin);
background = (UBYTE)getc(stdin);
AspByte = (UBYTE)getc(stdin);
if (AspByte!=0) aspect = ((float)((UWORD)AspByte + 15)) / 64.0;
BitsPerPixel = (gFlags & 0x07) + 1;
Colors= 1 << BitsPerPixel;
if ((Cregs = malloc(3*(unsigned)Colors)) == NULL) {
fprintf(stderr,"not enough memory for malloc()\n");
exit(50);
};
n=fread(Cregs,(int)Colors,3,stdin);
if ((c=getc(stdin))==0x2c) { /* process Image separator */
iLeft = fget16(stdin);
iTop = fget16(stdin);
iWidth = Width = fget16(stdin);
iHeight = Height = fget16(stdin);
iFlags = getc(stdin);
Interlace = (iFlags & 0x40);
if (iFlags & 0x80) {
iCol = (iFlags & 0x07) + 1;
BitsPerPixel = iCol;
Colors = iCol;
};
}
else {
fprintf(stderr,"No Image separator found\n");
exit(30);
};
if (AspByte == 0) {
if ((Width==320) && (Height==200)) aspect=1.2;
else if ((Width==640) && (Height==480)) aspect=1.0;
else if ((Width==640) && (Height==350)) aspect=1.37142857;
else aspect = 1.0;
};
if (Height>2048) {
fprintf(stderr,"Image too large (Height > 2048)\n");
exit(40);
};
for (i=0; i<Height; i++) {
if ((PixelBuffer[i]=malloc((unsigned)Width))==NULL) {
fprintf(stderr,"not enough memory for the pixelbuffer\n");
exit(50);
};
setmem(PixelBuffer[i],(unsigned)Width,0);
};
for (i=0; i<4096; i++) Prefix[i]=Suffix[i]=0;
fprintf(stderr,"Reading %u*%u Image\n",(unsigned)Width,(unsigned)Height);
/* Rasterdaten lesen -- Beginn */
BitMask = Colors - 1;
#ifdef DEBUG
printf("BitMask=%u\n",(unsigned)BitMask);
#endif
CodeSize = getc(stdin);
ClearCode = (1 << CodeSize);
EOFCode = ClearCode + 1;
FreeCode = FirstFree = ClearCode + 2;
CodeSize++;
InitCodeSize = CodeSize;
MaxCode = (1 << CodeSize);
#ifdef DEBUG
printf("CodeSize=%u MaxCode=%u\n",(unsigned)CodeSize,(unsigned)MaxCode);
#endif
InCode = 0;
/* Decompress */
Code = getbits(CodeSize);
if (FileTerminate) {
goto Corrupt_GIF;
};
while (Code != EOFCode) {
if (Code == ClearCode) {
CodeSize = InitCodeSize;
MaxCode = (1 << CodeSize);
FreeCode = FirstFree;
CurCode = OldCode = Code = getbits(CodeSize);
if (FileTerminate) {
goto Corrupt_GIF;
};
FinChar = CurCode & BitMask;
AddToPixel((UBYTE)FinChar);
TCounter++;
}
else { /* Normal Data */
CurCode = InCode = Code;
#ifdef DEBUG
printf("[%x]\n",(unsigned)CurCode);
#endif
if (CurCode >= FreeCode) {
CurCode = OldCode;
OutCode[OutCount++] = FinChar;
TCounter++;
};
while (CurCode > BitMask) {
#ifdef DEBUG
printf("=%x=\n",(unsigned)CurCode);
#endif
if (OutCount > 1024) {
Corrupt_GIF:
#ifdef DEBUG
printf("BitMask=%u\n",(unsigned)BitMask);
#endif
goto save_image;
};
TCounter++;
OutCode[OutCount++] = Suffix[CurCode];
CurCode = Prefix[CurCode];
};
FinChar = CurCode & BitMask;
TCounter++;
OutCode[OutCount++] = FinChar;
for (i = OutCount-1; i>=0; i--) AddToPixel((UBYTE)OutCode[i]);
OutCount = 0;
#ifdef DEBUG
printf(" F(%d)=(%xP|%xS) ",FreeCode,OldCode,FinChar);
#endif
Prefix[FreeCode] = OldCode;
Suffix[FreeCode] = FinChar;
OldCode = InCode;
FreeCode++;
if (FreeCode >= MaxCode) {
if (CodeSize < 12) {
CodeSize++;
MaxCode <<= 1;
};
};
}; /* else */
Code = getbits(CodeSize);
if (FileTerminate) {
goto Corrupt_GIF;
};
}; /* while */
save_image:
fprintf(stderr,"Writing %u*%u FBM-Bitmap\n",(unsigned)Width,(unsigned)Height);
WriteFBM(Height,Width);
for (i=0; i<Height; i++) free(PixelBuffer[i]);
}